﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GnufBase.h"
#ifndef _GNUF_WIP_TEST_HOTKEY_MANAGER_2_LOGIC_
#include <QtCore/QObject>

class QKeyEvent;
class QKeySequence;
class QMouseEvent;
namespace gnuf {

    class ButtonToolDefinition;
    class Info;
    class HotKeyInputBox;
    struct SingleHotkeySetting
    {
        SingleHotkeySetting()
            : wantToBeTracked(true), wantToBePrompted(true), wantToBeTriggered(true)
            , buttonInfo(nullptr) {}
        SingleHotkeySetting(
            const std::wstring & _1, const std::wstring & _2, const std::list<std::wstring> & _3,
            bool _4, bool _5, bool _6,
            const Info * _7)
            : key(_1), cmdId(_2), submitKeys(_3)
            , wantToBeTracked(_4), wantToBePrompted(_5), wantToBeTriggered(_6)
            , buttonInfo(_7) {}
        std::wstring key; std::wstring cmdId; std::list<std::wstring> submitKeys; // _1, _2, _3
        bool wantToBeTracked; bool wantToBePrompted; bool wantToBeTriggered; // _4, _5, _6
        const Info* buttonInfo; // _7
    };

    class HotkeyGroup
    {
    public:
        HotkeyGroup(const std::wstring& caption , const std::wstring& whatsThis, const std::list<std::wstring>& submitKeys);
        ~HotkeyGroup();

        const std::vector<SingleHotkeySetting>& HotKeySettings() const { return m_hotKeySettings; }
        std::vector<SingleHotkeySetting>& GetHotKeySettings() { return m_hotKeySettings; }
        std::wstring Caption() const { return m_groupCaption; }
        std::wstring WhatIsThis() const { return m_whatIsThis; }
        std::list<std::wstring> SubmitKeys() const { return m_submitKeys;}
        std::wstring SubmitKeysToString() const;

        bool isExistKeySetting(const std::wstring &key, SingleHotkeySetting& setting) const;
        void AddHotKeySetting(const SingleHotkeySetting& setting) { m_hotKeySettings.push_back(setting); }
        void DeleteHotKeySetting(const std::wstring &key);
        void UpdateHotKeySetting(const std::wstring& oldKey, const std::wstring& newKey, const SingleHotkeySetting& setting);
    private:
        friend class HotkeyManager;
        std::wstring m_groupCaption;
        std::wstring m_whatIsThis;
        std::list<std::wstring> m_submitKeys;
        std::vector<SingleHotkeySetting> m_hotKeySettings;
    };

    class GNUF_BASE_EXPORT HotkeyManager final
    {
        CANNOT_COPY_OR_ASSIGN(HotkeyManager)

    public:
        enum class HotkeyMode : std::uint32_t
        {
            ePromoter = 0,
            eBottomToolBar
        };

        static HotkeyManager* get();

        bool AddHotKey(
            const std::wstring& cmdId,const std::wstring& key, const std::list<std::wstring>& submitKeys,
            bool wantToBeTracked, bool wantToBePrompted, bool wantToBeTriggered, 
            const std::wstring& groupName);
        bool AddHotKey(
            const std::wstring& cmdId, const std::wstring& key, const std::list<std::wstring>& submitKeys,
            bool wantToBeTracked, bool wantToBePrompted, bool wantToBeTriggered, 
            HotkeyGroup* group);
        bool DeleteHotKey(const std::wstring& key);
        bool ReplaceHotKey(const std::wstring& oldKey, const std::wstring& newKey);

        HotkeyGroup* AddHotKeyGroup(const std::wstring& group, const std::wstring& whatIsThis, const std::list<std::wstring>& submitKeys);
        bool Update(const std::list<HotkeyGroup>& newHotKeyGroups);
        void UpdateKeyGroup(const std::wstring& oldKey, const std::wstring& newKey);

        void setVersion(const std::string &strVersion) { m_version = strVersion; }
        const std::string&  version() const { return m_version; }

        ButtonToolDefinition* GetButtonToolDefinitionByKey(const std::wstring& key) const;
        std::wstring GetHotKeyByCommandId(const std::wstring& cmd) const;
        const std::list<HotkeyGroup>& HotKeyGroups() const { return m_hotKeyGroups; }
        const std::list<HotkeyGroup>& ModifyHotKeyGroups() const { return m_modifyHotKeyGroups; }
        const HotkeyGroup* SystemHotKeyGroup() const;

        std::wstring GetHotKeyPromptMessage() const;
        void ResetHotKeyPromptMessage();

        typedef std::map<std::wstring, SingleHotkeySetting> Hotkeys;
        const HotkeyManager::Hotkeys & hotkeys() const { return m_hotKeyToSettingMap; }

        void SubmitAction(const std::wstring& hotkeyStream);
        void setHotkeyMode(HotkeyMode mode) { m_mode = mode; }
        bool isTriggerKey(QKeyEvent* qtEvt, const std::wstring& submitKey);
        bool isTempKey(const std::wstring& key) const;
        std::wstring buildTempKey() const;
    public:
        void onKeyEvent(QKeyEvent* qtEvt);
        void onKeySequenceEvent(QKeySequence seq);
        void onMouseButtonEvent(QMouseEvent* qtEvt);

    private:
        int getModifiyKeySequence(QKeyEvent* qtEvt);
        void initializeControl();

    private:
        enum class ETemporaryStatus : std::uint8_t
        {
            eCreation,
            eError,
            eCancel,
            eFinish,
            eNotUsable
        };

        HotkeyManager();
        ~HotkeyManager();

        void SetPromptMessage(ETemporaryStatus status);
        

    private:
        std::wstring m_promptMessage;
        std::map<std::wstring,ButtonToolDefinition*> m_hotKeyToDefinitionMap;
        HotkeyManager::Hotkeys m_hotKeyToSettingMap;
        std::list<HotkeyGroup> m_hotKeyGroups;
        std::list<HotkeyGroup> m_modifyHotKeyGroups;
        HotkeyMode m_mode;
        std::string m_version;
    };

}
#endif // _GNUF_WIP_TEST_HOTKEY_MANAGER_2_LOGIC_
